package com.wrupple.muba.common.domain;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import com.google.gwt.user.client.rpc.IsSerializable;

public class FilterData implements Serializable, IsSerializable {

	public static final String EQUALS = "==";
	public static final String GREATEREQUALS = ">=";
	public static final String LESSEQUALS = "<=";
	public static final String LESS = "<";
	public static final String GREATER = ">";
	
	private static final long serialVersionUID = 228729890736454589L;
	public static final String DIFFERENT = "!=";

	private Map<String, List<FilterCriteria>> filters;
	private ArrayList<FilterDataOrdering> order;
	private String[][] joins;
	private int start = 0;
	private int end = 30;
	private boolean constrained = true;

	public FilterData() {
		super();
		filters = new HashMap<String, List<FilterCriteria>>();
	}

	public FilterData(Map<String, List<FilterCriteria>> filters, ArrayList<FilterDataOrdering> order2) {
		super();
		this.filters = filters;
		order = order2;
	}

	public Map<String, List<FilterCriteria>> getFilters() {
		if (filters == null) {
			return new HashMap<String, List<FilterCriteria>>();
		}
		return filters;
	}

	public void setFilters(Map<String, List<FilterCriteria>> originalFilters) {
		this.filters = originalFilters;
	}

	public int getStart() {
		return start;
	}

	public void setStart(int start) {
		this.start = start;
	}

	public int getEnd() {
		return end;
	}

	public void setEnd(int end) {
		this.end = end;
	}

	/**
	 * @param constrained
	 *            the constrained to set
	 */
	public void setConstrained(boolean constrained) {
		this.constrained = constrained;
	}

	/**
	 * @return the constrained
	 */
	public boolean isConstrained() {
		return constrained;
	}

	/**
	 * @param order
	 *            the order to set
	 */
	public void setOrder(ArrayList<FilterDataOrdering> order) {
		this.order = order;
	}

	/**
	 * @return the order
	 */
	public ArrayList<FilterDataOrdering> getOrder() {
		if (order == null) {
			return new ArrayList<FilterDataOrdering>();
		}
		return order;
	}


	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + (constrained ? 1231 : 1237);
		result = prime * result + end;
		result = prime * result + ((filters == null) ? 0 : filters.hashCode());
		result = prime * result + ((order == null) ? 0 : order.hashCode());
		result = prime * result + start;
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		FilterData other = (FilterData) obj;
		if (constrained != other.constrained)
			return false;
		if (end != other.end)
			return false;
		if (filters == null) {
			if (other.filters != null)
				return false;
		} else if (!filters.equals(other.filters))
			return false;
		if (order == null) {
			if (other.order != null)
				return false;
		} else if (!order.equals(other.order))
			return false;
		if (start != other.start)
			return false;
		return true;
	}

	@Override
	public String toString() {
		return "{\"start\":" + start + ",\"end\":"
				+ end +  ",\"filters\":" + serialize(filters) + ", \"order\":" + order + ", \"constrained\":" + constrained + "}";
	}

	private String serialize(Map<String, List<FilterCriteria>> map) {
		if (map == null) {
			return null;
		}
		StringBuilder builder = new StringBuilder(map.size() * 20);
		Set<String> keys = map.keySet();
		builder.append('{');
		List<FilterCriteria> list = null;
		for (String key : keys) {
			list = map.get(key);

			if (list != null) {
				builder.append('\"');
				builder.append(key);
				builder.append("\":");
				builder.append(list.toString());
			}

		}
		builder.append('}');

		return builder.toString();
	}

	public FilterData copyExcludingRange() {
		FilterData filter = new FilterData(filters, order);
		return filter;
	}

	public String[][] getJoins() {
		return joins;
	}

	public void setJoins(String[][] joins) {
		this.joins = joins;
	}

}
